package vn.edu.saigontech.ncms.service.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Projections;

import vn.edu.saigontech.ncms.service.GenericService;
import vn.edu.saigontech.ncms.util.Checker;
import vn.edu.saigontech.ncms.util.HibernateUtil;

@SuppressWarnings("unchecked")
public class HibernateGenericService<E, ID extends Serializable> implements
		GenericService<E, ID> {

	protected Class<E> persistentClass;

	public HibernateGenericService() {
		this.persistentClass = (Class<E>) ((ParameterizedType) this.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public E persist(E entity) {
		try {
			this.getSession().saveOrUpdate(entity);
		} catch (Exception ex) {
			return null;
		}
		return entity;
	}

	public boolean deleteById(ID id) {
		try {
			this.getSession().delete(this.findById(id));
		} catch (Exception ex) {
			return false;
		}
		return true;
	}

	public E findById(ID id) {
		if (Checker.isNull(id))
			return null;
		return (E) this.getSession().get(this.persistentClass, id);
	}

	@Override
	public Collection<E> find(E entity) {
		Criteria criteria = this.createCriteria();
		criteria.add(Example.create(entity));
		return criteria.list();
	}

	public Collection<E> findAll() {
		return this.getSession().createCriteria(this.persistentClass).list();
	}
	
	@Override
	public E getFirst() {
		List<E> list = (List<E>) this.findAll();
		if(!list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	public int countAll() {
		Criteria criteria = this.createCriteria();
		criteria.setProjection(Projections.rowCount());
		return (Integer) criteria.uniqueResult();
	}

	protected Session getSession() {
		return HibernateUtil.getCurrentSession();
	}

	protected Criteria createCriteria() {
		return this.getSession().createCriteria(this.persistentClass);
	}
}